package com.bsj.sipgateway.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.constant.NumericalConstants;
import com.bsj.power.common.def.dto.room.RoomDTO;
import com.bsj.power.common.def.dto.room.RoomSearchDTO;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.power.common.def.entity.room.Room;
import com.bsj.power.common.def.vo.video.room.RoomVO;
import com.bsj.power.common.mapper.DeviceMapper;
import com.bsj.power.common.mapper.RoomMapper;
import com.bsj.power.common.util.DateUtils;
import com.bsj.power.common.util.ParamCheckUtil;
import com.bsj.sipgateway.common.constant.Constants;
import com.bsj.sipgateway.util.RedisDeviceInfoUtil;
import com.bsj.sipgateway.web.service.RoomService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author LiJiaXin
 * @version 1.0.0
 * @description RoomServiceImpl
 * @time 2024/9/3 11:24
 */
@Service("roomServiceImpl")
public class RoomServiceImpl implements RoomService {

    @Resource
    private RoomMapper roomMapper;

    @Resource
    private DeviceMapper deviceMapper;

    @Autowired
    private RedisDeviceInfoUtil redisDeviceInfoUtil;

    /**
     * 添加房间
     *
     * @param roomDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/9/3 12:05
     */
    @Override
    @Transactional
    public JsonResult addRoom(RoomDTO roomDTO) {
        //房间号去重
        if (roomMapper.exists(Wrappers.<Room>lambdaQuery().eq(Room::getRoomNo, roomDTO.getRoomNo()))) {
            return JsonResult.fail(JsonResultEnum.ROOM_NO_EXIST);
        }
        Room room = new Room();
        BeanUtils.copyProperties(roomDTO, room);
        if (roomMapper.insert(room) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 删除房间
     *
     * @param roomId
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/9/3 12:05
     */
    @Override
    @Transactional
    public JsonResult deleteRoom(Long roomId) {
        ParamCheckUtil.isNull(roomId);
        Room room = roomMapper.selectById(roomId);
        ParamCheckUtil.isNull(room, JsonResultEnum.ROOM_NOT_EXIST);
        //如果房间有摄像头不允许删除
        if(deviceMapper.exists(Wrappers.<Device>lambdaQuery().eq(Device::getRoomNo,room.getRoomNo()))){
            throw new ApiException(JsonResultEnum.ROOM_EXIST_VIDEO_DEVICE);
        }
        if (roomMapper.deleteById(roomId) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 修改房间
     *
     * @param roomDTO
     * @return com.bsj.power.common.config.global.JsonResult
     * @author ljx
     * @time 2024/9/3 12:05
     */
    @Override
    @Transactional
    public JsonResult updateRoom(RoomDTO roomDTO) {
        Long roomId = roomDTO.getRoomId();
        ParamCheckUtil.isNull(roomId);
        if (roomMapper.exists(Wrappers.<Room>lambdaQuery().eq(Room::getRoomNo, roomDTO.getRoomNo()).ne(Room::getRoomId, roomId))) {
            return JsonResult.fail(JsonResultEnum.ROOM_NO_EXIST);
        }
        Room room = new Room();
        BeanUtils.copyProperties(roomDTO, room);
        if (roomMapper.updateById(room) > NumericalConstants.ZERO) {
            return JsonResult.success();
        } else {
            return JsonResult.fail();
        }
    }

    /**
     * 获取单个房间信息
     *
     * @param roomId
     * @return com.bsj.power.common.def.vo.video.room.RoomVO
     * @author ljx
     * @time 2024/9/3 12:05
     */
    @Override
    public RoomVO getRoomById(Long roomId) {
        ParamCheckUtil.isNull(roomId);
        Room room = roomMapper.selectById(roomId);
        ParamCheckUtil.isNull(room, JsonResultEnum.ROOM_NOT_EXIST);
        RoomVO roomVO = new RoomVO();
        BeanUtils.copyProperties(room, roomVO);
        return roomVO;
    }

    /**
     * 房间信息分页
     *
     * @param roomSearchDTO
     * @return com.bsj.power.common.config.global.JsonResult<java.util.List < com.bsj.power.common.def.vo.video.room.RoomVO>>
     * @author ljx
     * @time 2024/9/3 12:04
     */
    @Override
    public JsonResult<List<RoomVO>> pageRoom(RoomSearchDTO roomSearchDTO) {
        List<RoomVO> roomVOS = new LinkedList<>();
        IPage<Room> page = new Page<>(roomSearchDTO.getPageNumber(), roomSearchDTO.getPageSize());
        QueryWrapper<Room> queryWrapper = new QueryWrapper<>();
        String roomNo = roomSearchDTO.getRoomNo();
        Integer unitNo = roomSearchDTO.getUnitNo();
        if (StringUtils.isNotBlank(roomNo)) {
            queryWrapper.eq("room_no", roomNo);
        }
        if (unitNo != null) {
            queryWrapper.eq("unit_no", unitNo);
        }
        IPage<Room> iPage = roomMapper.selectPage(page, queryWrapper);
        long total = iPage.getTotal();
        List<Room> rooms = iPage.getRecords();
        if (total == NumericalConstants.ZERO || CollectionUtils.isEmpty(rooms)) {
            return JsonResult.success(roomVOS, total);
        }
        roomVOS = rooms.stream().map(room -> {
            RoomVO roomVO = new RoomVO();
            BeanUtils.copyProperties(room, roomVO);
            roomVO.setCreateTime(DateUtils.dateToStr(room.getCreateTime()));
            roomVO.setUpdateTime(DateUtils.dateToStr(room.getUpdateTime()));
            return roomVO;
        }).collect(Collectors.toList());
        return JsonResult.success(roomVOS, total);
    }

    /**
     * 根据房间号查询视频设备信息
     *
     * @param roomNo
     * @return com.bsj.power.common.def.vo.video.room.RoomVO
     * @author ljx
     * @time 2024/9/8 20:28
     */
    @Override
    public RoomVO getVideoDevicesByRoomNo(String roomNo) {
        RoomVO roomVO = new RoomVO();
        if (StringUtils.isBlank(roomNo)) {
            return roomVO;
        }
        Room room = roomMapper.selectOne(Wrappers.<Room>lambdaQuery().eq(Room::getRoomNo, roomNo));
        if (room == null) {
            return roomVO;
        }
        BeanUtils.copyProperties(room, roomVO);
        //查询视频设备信息
        List<Device> devices = deviceMapper.selectList(Wrappers.<Device>lambdaQuery().eq(Device::getRoomNo, roomNo));
        for (Device device : devices) {
            // 获取在线离线信息（查缓存）
            boolean onlineFlag = redisDeviceInfoUtil.checkOnline(device.getDeviceId());
            if (onlineFlag) {
                device.setOnline(Constants.DEVICE_ONLINE);
            } else {
                device.setOnline(Constants.DEVICE_OFFLINE);
            }
        }

        roomVO.setDevices(devices);
        return roomVO;
    }
}
